达人探店
要点:
- Set 的使用
- ZSet 的使用
1.1 探店笔记
1.1.1 发布探店笔记
表结构
这个功能涉及到两张表
tb_blog:探店笔记表,包含笔记中的标题、文字、图片等

tb_blog_comments:其他用户对探店笔记的评价
1.1.2 查看探店笔记
这里不仅要获取blog的基本数据,还要获取用户的一些基本数据
代码实现
java@Override public Result getBlogById(Integer id) { Blog blog = blogMapper.selectById(id); if (blog == null) { return Result.fail("博客不存在!"); } queryBlogUser(blog); return Result.ok(blog); } private void queryBlogUser(Blog blog) { Long userId = blog.getUserId(); User user = userService.getById(userId); blog.setName(user.getNickName()); blog.setIcon(user.getIcon()); }
1.2 点赞
需求
- 同一个用户只能点赞一次,再次点击则取消点赞
- 如果当前用户已经点赞,则点赞按钮高亮显示
实现步骤
- 给 Blog 类中添加一个 isLike 字段,标示是否被当前用户点赞
- 修改点赞功能,利用 Redis 的 set 集合判断是否点赞过,未点赞过则点赞数+1,将用户放到set集合中 ,已点赞过则点赞数 -1,将用户从set集合中取出
- 修改根据 id 查询 Blog 的业务,判断当前登录用户是否点赞过,赋值给 isLike 字段
- 修改分页查询 Blog 业务,判断当前登录用户否点赞过,赋值给 isLike 字段
核心代码
java/** * * 判断博客是否被当前用户点赞过 * * @param blog * @return {@link Boolean } */ private void isBlogLiked(Blog blog) { UserDTO user = UserHolder.getUser(); if (user == null) { // 用户未登录,无需查询是否点赞 return; } Long userId = user.getId(); String key = BLOG_LIKED_KEY + blog.getId(); Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString()); // 点赞过设为 true 未点赞过设置为 false blog.setIsLike(BooleanUtil.isTrue(isMember)); } @Override public void likeBlog(Long id) { // 实现点赞逻辑 // 1. 修改点赞功能,利用 Redis 的 set 集合判断是否点赞过,未点赞过则点赞数+1,将用户放到set集合中 ,已点赞过则点赞数 -1,将用户从set集合中取出 Long userId = UserHolder.getUser().getId(); String key = BLOG_LIKED_KEY + id; Boolean liked = stringRedisTemplate.opsForSet().isMember(key, userId.toString()); // 2. 如果未点赞过,则点赞数+1,将用户放到set集合中 if (!Boolean.TRUE.equals(liked)) { // 更改数据库 boolean success = update().setSql("liked = liked + 1").eq("id", id).update(); // 更改 Redis if (success) { stringRedisTemplate.opsForSet().add(key, userId.toString()); } } else { // 3. 如果点赞过,则点赞数 -1,将用户从set集合中取出 boolean success = update().setSql("liked = liked - 1").eq("id", id).update(); if (success) { stringRedisTemplate.opsForSet().remove(key, userId.toString()); } } }
1.3 排行榜
需求
- 点赞的用户应该在博客下方展示出来,按照权重排名
- 展示top5
实现思路
- 改用Zset,将用户放入集合时,将当前集合的个数作为 score ,将用户放入,最后展示的时候,升序排列,score低的排名高
代码实现
java@Override public Result queryBlogLikesTop5(Long id) { String key = BLOG_LIKED_KEY + id; // 1. 查询 Redis 中 zset 集合,查询点赞数前5的用户 id // Spring Data Redis 默认返回的是一个 LinkedHashSet,保证了插入顺序 Set<String> top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4); if (top5 == null || top5.isEmpty()) { return Result.ok(Collections.EMPTY_LIST); } // 2. 根据用户 id 查询用户信息 List<Long> ids = top5.stream().map(Long::valueOf).collect(Collectors.toList()); List<UserDTO> dtoList = userService.query().in("id", ids). last("ORDER BY FIELD(id," + StrUtil.join(",", ids) + ")") .list().stream() .map(user -> { UserDTO userDTO = new UserDTO(); userDTO.setId(user.getId()); userDTO.setIcon(user.getIcon()); userDTO.setNickName(user.getNickName()); return userDTO; }).collect(Collectors.toList()); return Result.ok(dtoList); }